Java类和对象


个人学习之后对于 Java 类和对象的理解

类是一个模板,它描述一类对象的行为和状态,从类到对象即为实例化,从对象到类为抽象

Java 类

Java 类分为外部类和内部类
类可以看成是创建 Java 对象的模板
eg. 创建一个狗的类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Dog{
String breed; //品种
int age; //年龄
String color; //颜色

//以下为该 Dog 类的方法
//叫
void barking(){
System.out.println("小狗在叫");
}

//饿
void hungry(){
System.out.println("小狗饿了");
}

//睡觉
void sleeping(){
System.out.println("小狗在睡觉");
}
}

Java 外部类

外部类只有 public 和 default(缺省) 两种修饰
如果一个类声明的时候使用了 public class 进行了声明,则类名称必须与文件名称完全一致
如果一个类声明的时候使用了 class 进行了声明,则作为启动类的名称可以与文件名称不一致,但是执行的时候肯定执行的是生成后的名称
在一个 *.java 文件中,只能有一个 public class 的声明(公共接口),但是允许有多个 class 声明;public 类不是必须的

1
2
3
4
5
6
7
8
9
//公开可访问,被 public 修饰的类可以被其他包访问
public class Student{

}

//同一个包内可访问,该类不能被其他包访问
class{

}

Java 内部类

在外部类的内部再声明一个类则称为内部类,内部类有:静态内部类、成员内部类、局部内部类、匿名内部类
内部类均可结合变量进行理解

静态内部类

静态内部类可以等同看作静态变量,可以用 public,protected,private 修饰
可以定义静态或者非静态的成员
静态内部类的作用是:可以访问外部类中私有的数据
看到带有 $ 符号的 .class 文件基本是内部类
静态内部类可以直接访问外部类的静态数据,无法直接访问成员
eg.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
/*
* 关于静态内部类
* 1、静态内部类可以等同看作静态变量
*
* 内部类重要的作用:可以访问外部类中私有的数据
*
* 2、静态内部类可以直接访问外部类的静态数据,无法直接访问成员
*/
public class OuterClass {

//静态变量
static String s1 = "A";

//成员变量
private static String s2 = "B";

//静态方法
private static void m1() {
System.out.println("static's m1 method execute!");
}

//成员方法
private void m2() {
System.out.println("m2 method execute!");
}

//静态内部类
//可以用访问控制权限的修饰符修饰
//public,protected,private,缺省

static class InnerClass{

//静态方法
public static void m3() {
System.out.println(s1);
m1();

//System.out.println(s2);
//m2();
}

//成员方法
public void m4() {
System.out.println(s1);
m1();

//System.out.println(s2);
//m2();

}
}

//入口
public static void main(String[] args) {

//执行 m3
OuterClass.InnerClass.m3();

//执行 m4
InnerClass inner = new OuterClass.InnerClass();
inner.m4();
}
}

成员内部类

成员内部类可以等同看作成员变量
区别于局部内部类的地方是定义在方法外
成员内部类中不能有静态声明
成员内部类可以访问外部类所有的数据
eg.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/*
* 关于成员内部类
*
* 1、成员内部类可以等同看作成员变量
*
* 2、成员内部类中不能有静态声明
*
* 3、成员内部类可以访问外部类所有的数据
*/
public class OuterClass02 {

// 静态变量
static String k1 = "A";

// 成员变量
private static String k2 = "B";

// 静态方法
private static void y1() {
System.out.println("static's y1 method execute!");
}

// 成员方法
private void y2() {
System.out.println("y2 method execute!");
}

// 成员内部类
// 可以用访问控制权限的修饰符修饰
// public,protected,private,缺省
class InnerClass {

// 静态方法
/*
* public static void y3() {
*
* }
*/

// 成员方法
public void y4() {
System.out.println(k1);
y1();

System.out.println(k2);
y2();

}
}

// 入口
public static void main(String[] args) {

// 创建外部类对象

OuterClass02 oc = new OuterClass02();
InnerClass inner = oc.new InnerClass();

inner.y4();
}
}

局部内部类

局部内部类等同于局部变量
区别于成员内部类的地方是定义在方法内
局部内部类不能有静态声明
重点:局部内部类在访问局部变量的时候,局部变量必须使用 final 修饰
eg.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/*
* 局部内部类等同于局部变量
*
* 重点:局部内部类在访问局部变量的时候,局部变量必须使用 final 修饰
*/
public class OuterClass03 {

//方法
public void f1() {

//局部变量
final int i = 10;

//局部内部类
//局部内部类不能用访问控制权限修饰符修饰
class InnerClass{

//内部类不能有静态声明
//public static void m1() {}

//成员方法
public void f2() {
System.out.println(i);//10
}
}

//调用 m2
InnerClass inner = new InnerClass();
inner.f2();
}

//入口
public static void main(String[] args) {
OuterClass03 oc = new OuterClass03();
oc.f1();
}
}

匿名内部类

匿名类不能使用任何关键字和访问控制符

eg.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/*
* 匿名内部类:指的是类没有名字
*/
public class Test01 {

//静态方法
public static void t(CustomerService cs) {
cs.logout();
}

//入口
public static void main(String[] args) {

//调用 t 方法
//t(new CustomerServiceImpl());

//使用匿名内部类的方式执行 t 方法
//整个这个 "new CustomerService(){}" 就是个匿名内部类
t(new CustomerService() {
public void logout() {
System.out.println("系统已经安全退出!");
}
});

//匿名内部类的优点:少定义一个类
//缺点:无法重复使用!

}

}

//接口
interface CustomerService{

//退出系统
void logout();
}

//不使用匿名内部类的情况
//编写一个类实现 CustomerService 接口
/*
class CustomerServiceImpl implements CustomerService{

public void logout() {
System.out.println("系统已经安全退出!");
}
}
*/

局部、静态、成员内部类的访问区别

eg. 局部内部类的访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//访问局部内部类必须先有外部类对象
public class Outer{
public void f(final int k){
//局部内部类
class Inner{//定义在方法内部
……
}
}
public static void main(String[] args){
//访问局部内部类必须先有外部类对象
Outer out = new Outer();
out.f(2);
}
}

eg. 静态内部类的访问

1
2
3
4
5
6
7
8
9
10
11
12
13
//外部类访问内部类的非静态成员:实例化内部类即可
public class Outer{
//静态内部类
static class Inner{
static void inner_f1(){
}
}
public void outer_f2{
//访问
Inner inn = new Inner();
inn.inner_f1();
}
}

eg. 成员内部类的访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Outer{
class Inner{
void inner_f1(){
……
}
}
//外部类的非静态方法访问成员内部类
public void outer_f1(){
Inner inn = new Inner();
inn.inner_f1();
}
//外部类的静态方法访问成员内部类
public static void outer_f2(){
//建立外部类对象
Outer out = new Outer();
//根据外部类对象建立内部类对象
Inner inn = out.new Inner();
//访问内部类的方法
inn.inner_f1();
}
}

对象

面向对象三大特征:封装、继承、多态

1
1. 封装:问权限控制 public > protected > 缺省 > private 内部类也是一种封装

public 公开,任何位置都可以访问
protected 同包,子类
缺省 同胞
private 私有,只能在本类中访问

1
2
3
2. 继承:一般类只能单继承,内部类实现多继承,接口可以多继承
3. 多态:编译时多态,体现在向上转型和向下转型,通过引用类型判断调用哪个方法(静态分派)。
运行时多态,体现在同名函数通过不同参数实现多种方法(动态分派)。

对象具有状态和行为,从类到对象即为实例化
从类中创造对象:

  • 声明:声明一个对象,包括对象名称和对象类型
  • 实例化:使用关键字 new 来创建一个对象
  • 初始化:使用 new 创建对象时,会调用构造方法初始化对象; eg. Dog gg = new Dog();
    eg. 下面创建一个名为 Puppy 的狗对象
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class Puppy{
    public Puppy(String name){
    //这个构造器仅有一个参数:name
    System.out.println("小狗的名字是 : " + name );
    }
    public static void main(String[] args){
    // 下面的语句将创建一个Puppy对象
    Puppy myPuppy = new Puppy( "tommy" );
    }
    }

实例化对象后访问实例变量和方法

1
2
3
4
5
6
//实例化对象
ObjectReference = new Constructor();
//访问类中的变量
ObjectReference.variableName;
//访问类中的方法
ObjectReference.methodName();

eg. 定义一个计算机类和学生类,让其中一个学生去使用其中的一台某品牌的某型号笔记本电脑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/*
* 需求:
* 定义一个计算机类(电脑/笔记本)属性:
* - 品牌
* - 型号
* - 颜色
*
* 定义一个学生类属性:
* - 学号
* - 姓名
* - 学生有一台笔记本电脑
*
* 请编写程序来表示以上的类,分别将类创建为对象
* 对象数量不限,然后让其中的一个学生去使用其中的一台笔记本电脑
*
* 编译并运行,并且将整个执行过程采用图形的方式描述出来
*/
public class OOTest06 {

public static void main(String[] args) {

Computer emt = new Computer();
emt.brand = "SummerCommpany";
emt.number = "SUM-002";

Stuu kmt = new Stuu();
kmt.no = 6623798;
kmt.name = "WiHieree";

emt.s = kmt;
kmt.c = emt;

System.out.println(kmt.name + " 使用的电脑是 " + kmt.c.brand + " 旗下的 " + kmt.c.number);


}


}

class Computer{

String brand;
String number;
String col;
Stuu s;

}

class Stuu{

int no;
String name;
Computer c;
}

封装

所有属性私有化,使用 private 关键字进行修饰,private 表示私有的,修饰的所有数据,使得数据只能在本类访问
封装主要是因为 Java 有访问权限的控制 public > protected > package > default > private

1
2


封装可以保护类中的信息,只提供想要被外界访问的信息
对外提供简单的操作入口

1
2
3
4
5
6
7
8
9
10
11
1. 对外提供两个公开的方法,分别是 set 方法和 get 方法
2. 想修改 age 属性,调用 set 方法
命名规范:
public void setAge(int a){

}
3. 想读取 age 属性,调用 get 方法
命名规范:
public int getAge(){
return age;
}

eg. 新建一个 User.java ,并进行封装保证输入年龄在合理范围内

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.wihieree01;

public class User {

//属性私有化
private int age;

/*
set 方法没有返回值,因为 set 方法只负责修改数据
public void setAge(int age) {
age = age; // Java 有就近原则,这里其实并没有给 age 属性赋值,这里的 age 都是局部变量 age
}
*/

public void setAge(int a) {

//编写业务逻辑代码进行安全控制
//age = a;

if(a <0 || a > 150) {
System.out.println("对不起,您提供的年龄不合法");
return;
}

//程序可以执行到这里,说明 a 年龄是合法的,则进行赋值运算
age = a;
}

//getter
public int getAge() {
return age;
}

}

eg. 新建一个 UserTest.java 创建一个 User 对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.wihieree01;

public class UserTest {

public static void main(String[] args) {

//创建 User 对象
User user = new User();

//编译报错,age 属性私有化,在外部程序中不能直接访问
//从此之后 age 属性非常安全,但是有点太安全了
//对于目前的程序来说,age 属性彻底在外部访问不到了
//System.out.println(user.age);
//在 User.Java 添加 setter and getter 方法

//修改
//user.setAge(-100); //对不起,您提供的年龄不合法
user.setAge(23); // 23

//读取
System.out.println(user.getAge());

}

}

构造方法

构造方法的作用:创建对象和在创建对象的同时,初始化实例变量的内存空间
eg. 创建一个银行客户对象,查看户主名称,账号和余额

  1. 创建一个 Account.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    package com.wihieree02;

    //账户类
    public class Account {

    //户主
    private String name;
    //账号
    private String actno;
    //余额
    private double balance;

    //有参数构造方法
    public Account(String name,String actno,double balance){

    this.name = name;
    this.actno = actno;
    this.balance = balance;

    }

    //封装 get / set
    public String getName() {
    return name;
    }

    public void setName(String name) {
    this.name = name;
    }

    public String getActno() {
    return actno;
    }

    public void setActno(String actno) {
    this.actno = actno;
    }

    public double getBalance() {
    return balance;
    }

    public void setBalance(double balance) {
    this.balance = balance;
    }

    }
  2. 创建一个 ConstructorTest.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    package com.wihieree02;

    public class ConstructorTest02 {

    public static void main(String[] args) {

    //查看访问的是哪个属性按 Ctrl + 鼠标移动到查看的元素上单击
    //创建对象
    Account act1 = new Account("WiHieree","SUM-0984",1980000.0);

    System.out.println("户主:" + act1.getName()); //户主:WiHieree
    System.out.println("账号:" + act1.getActno()); //账号:SUM-0984
    System.out.println("余额:" + act1.getBalance()); //余额:1980000.0

    }

    }

继承

继承的基本作用是:代码复用,但是继承最重要的作用是:有了继承才有了以后方法的覆盖和多态机制
Java 中的继承只能单继承,但是可以通过内部类继承其他类来实现多继承
语法结构:

1
2
3
4
5
6
7
[修饰符列表] class 类名 extends 父类名{//关键字 extends
类体 = 属性 + 方法
}

// 私有的不支持继承
// 构造方法不支持继承
// 其他数据都可以被继承

虽然 java 语言当中只支持单继承,但是一个类也可以间接继承其它类,例如:

1
2
3
4
5
6
7
C extends B{
}
B extends A{
}
A extends T{
}
// C 直接继承 B 类,但是 C 类间接继承 T、A类

java 中假设一个类没有显示的继承任何类,该类默认继承 JavaSE 库当中提供的 java.lang.Object 类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.day1403;

public class ExtendsTest02 {

public static void main(String[] args) {
C c = new C();
//B 继承 A ,C 继承 B ,即 C 间接继承 A,所以 c. 可以访问 A 中的 doSome(); 方法
c.doSome();
}
}

class A{
public void doSome() {
System.out.println("do some!");
}
}

class B extends A{

}

class C extends B{

}

方法覆盖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
关于 java 语言当中方法的覆盖:
1、方法覆盖又被称为方法重写,override/overwrite

2、什么时候使用方法重写
当父类中的方法已经无法满足当前子类的业务需求
子类有必要将父类中继承过来的方法进行重新编写
这个重新编写的过程称为方法重写/方法覆盖

3、什么条件满足之后方法会发生重写呢 [代码满足什么条件之后,就构成方法的覆盖呢]
方法重写发生在具有继承关系的父子类之间
返回值类型相同,方法名相同,形参列表相同
访问权限不能更低,可以更高
抛出异常不能更多,可以更少 [以后讲]

4、建议方法重写的时候尽量复制粘贴,不要编写,容易出错,导致没有产生覆盖

5、注意:
私有方法不能继承,所以不能覆盖
构造方法不能继承,所以不能覆盖
静态方法不存在覆盖
覆盖只针对方法,不谈属性

eg.

  1. 新建一个 Animal.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    package com.day1404;

    //动物类
    public class Animal {

    //动物都是可以移动的
    public void move() {
    System.out.println("动物在移动");
    }
    }
  2. 新建一个 Bird.java 去继承 Animal ,此时鸟儿是在飞,要满足鸟儿飞就需要方法覆盖

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    package com.day1404;

    //飞禽类
    public class Bird extends Animal{

    //方法覆盖
    public void move() {
    System.out.println("鸟儿在飞行");
    }

    }
  3. 新建一个 Cat.java 去继承 Animal ,此时猫应该是走猫步,满足这个条件需要方法覆盖

    1
    2
    3
    4
    5
    6
    7
    8
    9
    package com.day1404;

    //猫科类
    public class Cat extends Animal{

    public void move() {
    System.out.println("猫在走猫步");
    }
    }
  4. 建一个测试 OverrideTest01.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    public class OverrideTest01 {

    public static void main(String[] args) {

    //创建动物对象
    Animal a = new Animal();
    a.move(); //动物在移动

    //创建猫科类动物对象
    Cat c = new Cat();
    c.move(); //猫在走猫步

    //创建飞禽类动物对象
    Bird b = new Bird(); //鸟儿在飞行
    b.move();
    }
    }

多态

多态语法机制,暂时参考上面的 Animal.java 和 Cat.java
使用多态语法机制:

1
2
3
4
Animal a1 = new Cat(); 
//向下类型转换 父类 --> 子类
Cat c1 = (Cat)a1;
//当调用的方法或者访问的属性是子类型中特有的,在父类型当中不存在,必须进行向下转型

eg.

  1. 修改 Cat.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    package com.day1405;

    //猫类
    public class Cat extends Animal{

    //重写父类中继承过来的方法
    public void move() {
    //!!!super 关键字
    //若重写后还是想要输出父类 Animal 的 move() 方法
    //super.move(); //动物在移动
    System.out.println("猫在溜达溜达");
    }

    //子类对象特有的行为
    public void catchMouse() {
    System.out.println("猫抓老鼠!");
    }
    }
  2. 修改 Bird.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    package com.day1405;

    //鸟儿类
    public class Bird extends Animal{

    //重写
    public void move() {
    System.out.println("鸟儿在飞翔");
    }

    public void fly() {
    System.out.println("Bird Fly");
    }

    }
  3. 新建 Test.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    package com.day1405;

    public class Test {

    public static void main(String[] args) {

    //使用多态语法机制
    Animal a1 = new Cat(); // 子类 --> 父类 称为向上转型
    a1.move(); //猫在溜达溜达 //结果主要看底层对象,底层对象是 Cat 调用的方法也是 Cat 对象的方法

    /*
    * 需求:
    * 假设想让以上的对象执行 catchMouse() 方法
    * a2 是无法直接调用的,因为 a2 类型 Animal,Animal 中没有 catchMouse() 方法
    * 我们可以将 a2 强制类型转换为 Cat 类型
    * a2 的类型是 Animal(父类),转换成 Cat 类型(子类),被称为向下转型/downcasting/强制类型转换
    *
    * 注:向下转型也需要两种类型之间必须有继承关系。不然编译器报错,强制类型转换需要加强制类型转换符
    *
    * 什么时候需要使用向下转型呢
    * 当调用的方法或者访问的属性是子类型中特有的,在父类型当中不存在,必须进行向下转型
    *
    */
    //向下转型
    Cat c1 = (Cat)a1;
    c1.catchMouse(); //猫抓老鼠!
    /*
    * long x = 100L;
    * int i = (int)i;
    */

    Animal a2 = new Bird();
    /*
    * 1、以下程序编译是没有问题的,因为编译器检查到 a2 的数据类型是 Animal,Animal 和 Cat 之间存在继承关系
    * 并且 Animal 是父类型,Cat 是子类型,父类型转换成子类型叫做向下转型,语法合格
    *
    * 2、程序虽然编译通过了,但是程序在运行阶段会出现异常,因为 JVM 堆内存当中真实存在的对象是 Bird 类型
    * Bird 对象无法转换成 Cat 对象,因为两种类型之间不存在任何继承关系,此时出现了著名的异常:
    * java.lang.ClassCastException
    * 类型转换异常,这种异常总是在"向下转型"的时候会发生
    *
    */

    //Cat c2 = (Cat)a2; // Bird 和 Cat 不存在继承关系

    /**
    * 1、以上异常只有在强制类型转换的时候会发生,也就是说"向下转型"存在隐患(编译通过,但是运行错误)
    * 2、向上转型只要编译通过,肯定可以运行 eg. Animal a = new Cat();
    * 3、向下转型编译通过,运行可能错误 eg. Animal a2 = new Bird(); Cat c2 = (Cat)a2;
    * 4、怎么避免向下转型出现的 ClassCastException
    * 使用 instanceof 运算符可以避免出现以上的异常
    * 5、instanceof 运算符:
    * 5.1、语法格式:
    * (引用 instanceof 数据类型名)
    * 5.2、以上运算符的执行结果类型是布尔类型,结果可能是 true/false
    * 5.3、关于运算结果 true/false
    * 假设:(a instanceof Animal)
    * true :
    * a 这个引用指向的对象是一个 Animal 类型
    * false:
    * a 这个引用指向的对象不是一个 Animal 类型
    * 6、Java 规范中要求:在进行强制类型转换之前,建议采用 instanceof 运算符进行判断,避免 ClassCastException 出现
    *
    */

    if(a2 instanceof Cat) {//a2 是一个 Cat 类型的对象
    Cat c2 = (Cat)a2;
    c2.catchMouse();
    }else if(a2 instanceof Bird) {//a3 是一个 Bird 类型的对象
    Bird b2 = (Bird)a2;
    b2.fly();
    }

    }
    }

eg. 多态在实际开发中的应用,主人喂养宠物

  1. 创建一个 Master.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    package com.day1501;

    public class Master{

    //Master 主人类面向的是一个抽象的 Pet,不再面向具体的宠物
    //提倡:面向抽象编程,不要面向具体编程
    //面向抽象编程的好处是,耦合度低,扩展力强
    public void feed(Pet pet) {// Pet pet 是一个父类型的引用
    pet.eat();
    }
    }
  2. 创建一个 Pet.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    package com.day1501;
    /*
    * 宠物
    */
    public class Pet {

    //所有的宠物都可以吃东西
    public void eat() {

    }
    }
  3. 创建一个 Cat.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    package com.day1501;

    /*
    * 宠物小猫
    */
    public class Cat extends Pet{

    //小猫爱吃鱼
    public void eat() {
    System.out.println("小猫在吃鱼!");
    }

    }
  4. 创建一个 Dog.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    package com.day1501;

    /**
    * 宠物小狗
    * @author SUMMER
    *
    */
    public class Dog extends Pet{

    public void eat() {
    System.out.println("小狗正在啃骨头!");
    }

    }
  5. 创建一个 Test.java 用于测试

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    package com.day1501;

    /*
    * 多态在实际开发中的作用,以下主人喂养宠物为例说明多态的作用:
    * 1、分析:主人喂养宠物这个场景要实现需要进行类型的抽象:
    * - 主人 [类]
    * - 主人可以喂养宠物,所以主人有喂养的这个动作
    * - 宠物 [类]
    * - 宠物可以吃东西,所以宠物有吃东西的这个动作
    *
    * 2、面向对象编程的核心:定义好类,然后将类实例化为对象,给一个环境驱使一下,
    * 让各个对象之间协作起来形成一个系统
    *
    * 3、多态的作用
    * 降低程序的耦合度,提高程序的扩展里
    * 能使用多态尽量使用多态
    * 父类型引用指向子类型对象
    *
    * 核心:面向抽象编程,尽量不要面向具体编程
    */
    public class Test {

    public static void main(String[] args) {
    //创建主人对象
    Master WiHieree = new Master();
    //创建猫对象
    Cat beer = new Cat();
    //主人喂养猫
    WiHieree.feed(beer);
    //创建小狗对象
    Dog yt = new Dog();
    //主人喂小狗
    WiHieree.feed(yt);
    }

    }

 Comments